#include "MarioGame.h"
using namespace std;

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000)? 1: 0)

CMarioGame::CMarioGame(HINSTANCE hInstance, LPCSTR GameName, LPSTR lpCmdLine, int nShowCmd, int FPS, int ScreenWidth, int ScreenHeight)
	:Game(hInstance, GameName, lpCmdLine, nShowCmd, FPS, ScreenWidth, ScreenHeight)
{

	CScreen::getInstance();
	CScreen::setSize(_screenWidth,_screenHeight);

	_MObjectList = std::list<shared_ptr<MObject>>();
	_staticObjectList = std::list<shared_ptr<MObject>>();
	_animateList = std::list<shared_ptr<MObject>>();
	_sightList = std::list<shared_ptr<Sight>>();
	_teleList = std::list<Teleport>();
	_checkPointList = std::list<Vector>();
	_hitBox = std::list<Vector>();
	_coll.setDeltaTime(1000/_FPS);
	_startMap = false;
	_mapLoaded = false;

	tree = shared_ptr<QuadTree>(new QuadTree(0,0));

	_sign = 1;

	if (strlen(lpCmdLine) > 0)
		_testMap = lpCmdLine;
	else
		_testMap = "";
	
}

CMarioGame::~CMarioGame(void)
{
	//delete mario;
	//mario.release();
}

void CMarioGame::ProcessMenu(int Action)
{
	switch (Action)
		{
		case CInfo::ACTION_NEWGAME:
			{
				_isContinue = false;
				NewMap("maps\\level1.map","");
				mario->Teleport(2,2);
				setStatus(STATUS_PLAYING);
				
				break;
			}
		case CInfo::ACTION_RESUME:
			{
				if (_mapLoaded == false)
					break;
				else
					setStatus(STATUS_PLAYING);
				break;
			}
		case CInfo::ACTION_SAVEGAME:
			{
				if (_mapLoaded == false)
					break;
				else
					SaveGame("maps\\save.mmf","maps\\save.inf");
				break;
			}
		case CInfo::ACTION_LOADGAME:
			{
				_isContinue = false;
				NewMap("maps\\save.mmf","maps\\save.inf");
				mario->Teleport(2,2);
				setStatus(STATUS_PLAYING);
				break;
			}
		case CInfo::ACTION_HELPMENU:
			{
				_background = _directX->LoadSurface(_rm->getLink(CResourceManager::HELPMENU),D3DCOLOR_XRGB(0,0,0));
				_info.setViewHelp(true);
				break;
			}
		case CInfo::ACTION_QUIT:
			{
				exit(0);
				break;
			}
		}
}

void CMarioGame::GameUpdate()
{
	////////////////////////////////////////////////////////////////////////////////////////////////////////
	//Processing when Mario finish current Map
	if (mario->getStatus() == CMario::STATUS_MOVENEXTMAP && mario->getPosition().getX() >= _finishRect.left + 730 && mario->getPosition().getX() <= _finishRect.left + 740)
	{
		mario->setScore(mario->getScore() + 1000);
		if (strcmp(_nextMap,"NONEXTMAP") == 0)
		{
			mario->getStatus() == CMario::STATUS_DEAD;
			mario->setLife(0);
		}
		else
		{

			_isContinue = true;
			NewMap(_nextMap,"");
			mario->Teleport(2,2);
			return;
		}
	}


	/////////////////////////////////////////////////////////////////////////////////////////////////////////
	//Processing Menu
	if (_gameStatus != STATUS_PLAYING)
	{
		int Action;
		_info.KeyProcess(Action);
		ProcessMenu(Action);
		return;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////
	//Processing Game Play
	std::list<shared_ptr<MObject>> objList = tree->getRoot()->getMovableObjects(_tRect,true);
	_MObjectList.insert(_MObjectList.end(),objList.begin(),objList.end());

	//Remove dead object
	std::list<shared_ptr<MObject>>::iterator it0 = _MObjectList.begin();
	while (it0 != _MObjectList.end())
	{
		if ((*it0)->getStatus() == -1 || (CScreen::getPosition().getX() - (*it0)->getPosition().getX()) > 800 || (*it0)->getPosition().getY() > 600 || (*it0)->getPosition().getX() < 0 || ((*it0)->getObjectType() == CResourceManager::TYPE_BULLET && abs((*it0)->getPosition().getX() - mario->getPosition().getX()) >= 600)) //STATUS_DEAD or Very Far Object from the screen
		{
			if ((*it0)->getStatus() == -1)
			{
					if ((*it0)->getObjectType() == CResourceManager::TYPE_MUSHROOM || (*it0)->getObjectType() == CResourceManager::TYPE_TURTLE)
						mario->setScore(mario->getScore() + (*it0)->getObjectScore());
					if ((*it0)->getObjectType() == CResourceManager::TYPE_FOOD)
						mario->setScore(mario->getScore() + (*it0)->getObjectScore());
			}
			_MObjectList.erase(it0++);
		} 
		else it0++;
	}


	for (std::list<shared_ptr<MObject>>::iterator checkedObj = _MObjectList.begin(); checkedObj != _MObjectList.end(); checkedObj++)
	{
		if (_coll.isIntersect((*checkedObj)->getRect(),_tRect))
			(*checkedObj)->Move();
		else continue;


		if ((*checkedObj)->getStatus() < 0) continue;
		for (std::list<shared_ptr<MObject>>::iterator checkedObj2 = checkedObj; checkedObj2 != _MObjectList.end(); checkedObj2++)
		{
			if ((*checkedObj2)->getStatus() <0) continue;
			if (_coll.inside((*checkedObj)->getRect(),(*checkedObj2)->getRect()))
				continue;


			//Chi xet va cham cac doi tuong cach checkedObj ko qua' 50px
			if (abs((*checkedObj)->getPosition().getX() - (*checkedObj2)->getPosition().getX()) <= 50 && abs((*checkedObj)->getPosition().getY() - (*checkedObj2)->getPosition().getY()) <= 50)
			{
				if (_coll.isIntersect((*checkedObj)->getRect(),(*checkedObj2)->getRect()))
					_coll.isCollided((*checkedObj),(*checkedObj2));
			}
		}

		//std::list<shared_ptr<MObject>> tList = tree->getRoot()->getCollidableObject((*checkedObj)->getRect());
		isFalling = true;

		for (std::list<shared_ptr<MObject>>::iterator it= _staticObjectList.begin();it != _staticObjectList.end();it++)
		{
			if ((*it)->isMovable()) continue;
			if ((*it)->getObjectType() == CResourceManager::TYPE_PIT && (*checkedObj)->getRect().left >= (*it)->getRect().left + 5 && (*checkedObj)->getRect().right <= (*it)->getRect().right - 5)
				continue;
			if ((abs((*it)->getPosition().getX() - (*checkedObj)->getPosition().getX()) > 150) || (abs((*it)->getPosition().getY() - (*checkedObj)->getPosition().getY()) > 150))
				continue;
			if ((*it)->getObjectType() == CResourceManager::TYPE_COIN)
				continue;
			if (_coll.isIntersect((*checkedObj)->getRect(),(*it)->getRect()))
				_coll.isCollided((*checkedObj),(*it));
			objRect = (*checkedObj)->getRect();
			objRect.left += 2;
			objRect.right -= 2;
			objRect.bottom += 2;

			if (_coll.isIntersect(objRect,(*it)->getRect()) && objRect.top + 32 <= (*it)->getPosition().getX())
				isFalling = false;
		}

		(*checkedObj)->setFallingStatus(isFalling);

	}


	//// check collision for Mario
	mario->Move();
	if (mario->getStatus() == CMario::STATUS_DEAD || _startMap)
	{
		if (mario->getLife() > 0)
		{
			mario->setStatus(CMario::STATUS_ALIVE);
			float minLength = MAXINT;
			float cpX = 0;
			float cpY = 0;
			for (std::list<Vector>::iterator it = _checkPointList.begin(); it != _checkPointList.end(); it++)
			{
				if ((*it).getX() <= mario->getPosition().getX())
				{
					if ((mario->getPosition().getX() - (*it).getX()) < minLength)
					{
						cpX = (*it).getX();
						cpY = (*it).getY();
						minLength = mario->getPosition().getX() - cpX;
					}
				}
			}
			if (cpX >= _cpX && cpY >= _cpY)
			{
				_cpX = cpX;
				_cpY = cpY;
			}
			if (!_startMap)
				mario->setLevel(1,true);
			mario->Teleport(_cpX,_cpY);
			_startMap = false;
			return;
		}
	}
	if (_coll.isIntersect(mario->getRect(),_finishRect))
		mario->setStatus(CMario::STATUS_MOVENEXTMAP);
	if (mario->getStatus() == CMario::STATUS_TOPIPE || mario->getStatus() == CMario::STATUS_OUTPIPE)
	{
		return;
	}
	if (mario->getStatus() >= 0)
	{
		isFalling = true;
		objRect = (mario)->getRect();
		objRect.bottom += 1.5f;
		objRect.left +=5;
		objRect.right -=5;

		for (std::list<shared_ptr<MObject>>::iterator it= _staticObjectList.begin(); it != _staticObjectList.end(); it++)
		{
			if ((*it)->getObjectType() == CResourceManager::TYPE_PIT && mario->getRect().left >= (*it)->getRect().left + 5 && mario->getRect().right <= (*it)->getRect().right - 5)
				continue;
			if ((*it)->getStatus() < 0) continue;
			if (abs((*it)->getPosition().getX() - (mario)->getPosition().getX()) > 50 && abs((*it)->getPosition().getY() - (mario)->getPosition().getY()) > 50)
				continue;
			if (_coll.isIntersect(objRect,(*it)->getRect()))
			{
				if ((*it)->getObjectType() == CResourceManager::TYPE_COIN)
				{
					(*it)->setStatus(-100);
					mario->setCoin(mario->getCoin() + 1);
					if (mario->getCoin() > 99)
					{
						mario->setCoin(0);
						mario->setLife(mario->getLife() + 1);
					}
					mario->setScore(mario->getScore() + (*it)->getObjectScore());
					CMarioSound::getInstance()->Play(CMarioSound::SOUND_GETCOIN,false);
					continue;
				}

				if ((*it)->getRect().top >= objRect.bottom - 2 && (objRect.left >= (*it)->getRect().left - 10) && (objRect.left <= (*it)->getRect().right - 10))
						isFalling = false;
					_coll.isCollided(mario,(*it));

					//collided with foodbox
					if ((*it)->getObjectType() == CResourceManager::TYPE_BOXWITHMUSHROOM && (*it)->getStatus() == FoodBox::STATUS_NORMAL && ((*it)->getPosition().getY() + 30 <= (mario->getPosition().getY())))
					{
						shared_ptr<MObject> food(new FoodMushroom((*it)->getPosition().getX(),(*it)->getPosition().getY() - 32,-0.5f,0,1000/_FPS,CResourceManager::MUSHROOMFOOD,_rm));
						if (mario->getLevel() == 1)
							food->setStatus(FoodMushroom::STATUS_MUSHROOM);
						else
							food->setStatus(FoodMushroom::STATUS_FLOWER);
							
						(*it)->setStatus(FoodBox::STATUS_EMPTY);
						_hitBox.insert(_hitBox.end(),Vector((*it)->getPosition().getX(),(*it)->getPosition().getY()));
						_MObjectList.insert(_MObjectList.end(),food);
						CMarioSound::getInstance()->Play(CMarioSound::SOUND_BONUSAPPEARED,false);

					}

					if (((*it)->getObjectType() == CResourceManager::TYPE_BRICK || ((*it)->getObjectType() == CResourceManager::TYPE_BOXWITHCOIN && (*it)->getStatus() != FoodBox::STATUS_EMPTY)) && mario->getVelocityVector().getY() <= 0 && (mario->getPosition().getY()>=(*it)->getPosition().getY() + 30))
					{
						if ((*it)->getObjectType() == CResourceManager::TYPE_BRICK)
						{
							if ((objRect.left + 16 >= (*it)->getRect().left && objRect.left <= (*it)->getRect().right - 5))
							{
								if (mario->getLevel() == 1)
     									(*it)->setStatus(Brick::STATUS_SLIDE);
								else if (mario->getLevel() >= 2)
									(*it)->setStatus(Brick::STATUS_SLIDE_BREAKED);
							}
						}
						else
						{
							mario->setScore(mario->getScore() + (*it)->getObjectScore());
							mario->setCoin(mario->getCoin() + 1);
							(*it)->setStatus(FoodBox::STATUS_EMPTY);
						_hitBox.insert(_hitBox.end(),Vector((*it)->getPosition().getX(),(*it)->getPosition().getY()));

						}
						_animateList.insert(_animateList.end(),(*it));
					}
					
			}
	 	}

		
		if (mario->getStatus() != CMario::STATUS_CHANGINGLEVEL)
		{
			for (std::list<shared_ptr<MObject>>::iterator it2= _MObjectList.begin(); it2 != _MObjectList.end(); it2++)
			{

				if ((*it2)->getStatus() < 0) continue;
				
				if (abs((*it2)->getPosition().getX() - (mario)->getPosition().getX()) > 50 && abs((*it2)->getPosition().getY() - (mario)->getPosition().getY()) > 50)
					continue;
				if (_coll.isIntersect(objRect,(*it2)->getRect()))
				{
						_coll.isCollided(mario,(*it2));

				}

				if (_coll.isIntersect(objRect,(*it2)->getRect()))
				{
					if (((*it2)->getStatus() == Gomba::STATUS_ALIVE) && (*it2)->getPosition().getY() - 30 > mario->getPosition().getY())
					{
						if ((*it2)->getObjectType() == CResourceManager::TYPE_TURTLE)
							(*it2)->setStatus(Turtle::STATUS_PUSHED);
						else
							if ((*it2)->getObjectType() == CResourceManager::TYPE_MUSHROOM)
								(*it2)->setStatus(Gomba::STATUS_DYING);
					}
				}
			}
		}
		mario->setFallingStatus(isFalling);
	}

	std::list<shared_ptr<MObject>>::iterator it3 = _animateList.begin();
	while (it3!= _animateList.end())
	{
		if ((*it3)->isAnimating())
		{
			(*it3)->Animate();
			it3++;
		}
		else
			_animateList.erase(it3++);

	}

	if (_delayShootTime > 0)
		_delayShootTime--;

	
}

void CMarioGame::RenderFrame()
{
	switch (_gameStatus)
	{
	case STATUS_PLAYING:
		{
			//Get Screen Rect
			_tRect = CScreen::getRect();
			_tRect.left-= 200;
			_tRect.right += 200;
	
			//Get All Visible Objects in Screen
			_staticObjectList = tree->getRoot()->getCollidableObject(_tRect);

			Vector v = CScreen::getInstance()->getPosition();

			//Sight Render
			for (std::list<shared_ptr<Sight>>::iterator it = _sightList.begin(); it != _sightList.end(); it++)
			{
				if (_coll.isIntersect((*it)->getRect(),_tRect))
				{
					(*it)->Render();
					if ((*it)->getSightType() == CResourceManager::TYPE_COLUMN2)
					{
						if (_winBarY > (*it)->getRect().bottom - 25 || _winBarY < (*it)->getRect().top + 25)
							_sign = -_sign;
						if (mario->getPosition().getX() <= _finishRect.left)
							_winBarY += _sign*0.25f*1000/_FPS;
					}
				}
			}
			//draw slide bar
			_bar->Render(_winBarX - v.getX(),_winBarY - v.getY());

			_pipeList = std::list<shared_ptr<MObject>>();
			std::list<shared_ptr<MObject>> list = tree->getRoot()->getCollidableObject(mario->getRect());
			for (std::list<shared_ptr<MObject>>::iterator it = _staticObjectList.begin();it!= _staticObjectList.end();it++)
			{
				if ((*it)->getObjectType() == CResourceManager::TYPE_CHIMNEY3)
					_pipeList.insert(_pipeList.begin(),(*it));
				else
					(*it)->Render();
			}

			for (std::list<shared_ptr<MObject>>::iterator it = _MObjectList.begin();it!= _MObjectList.end();it++)
				(*it)->Render();

			mario->Render();

			for (std::list<shared_ptr<MObject>>::iterator it = _pipeList.begin();it!= _pipeList.end();it++)
				(*it)->Render();

			/*if (_tScore < mario->getScore())
				_tScore+= 10;*/
			_info.Render(mario->getLife(), mario->getCoin(), mario->getScore());

			if (mario->getLife() == 0)
 				_info.RenderGameOver(334,292);

			break;
		}
	case STATUS_MENU:
		{
			_info.RenderMenu();
			break;
		}
	}
	
}

void CMarioGame::LoadMap(char* mapfile)
{
	ifstream inp(mapfile);
	float w,h;
	inp>>w;
	inp>>h;
	int tLevel;
	inp>>tLevel;
	int tLife;
	inp>>tLife;
	inp>>_cpX;
	inp>>_cpY;
	tree = shared_ptr<QuadTree>(new QuadTree(w*32,h*32));
	int tCoin;
	inp>>tCoin;
	int tScore;
	inp>>tScore;

	if (!_isContinue)
	{
		mario = shared_ptr<CMario>(new CMario(10,0,0,0,1000/_FPS,CResourceManager::MARIOSTANDLEFT1,_rm));
		mario->setLevel(1,false);
		mario->setLevel(tLevel,false);
		mario->setLife(tLife);
		mario->setCoin(tCoin);
		mario->setScore(tScore);
	}

	int i;
	int j;
	int count = 0;
	_nextMap = new char[255];

	if (inp)
	{
		for (int j = 0;j<h;j++)
			for (int k=0;k<w;k++)
			{
				inp>>i;
				switch (i)
				{
				case CResourceManager::TYPE_BRICK:
					{
						shared_ptr<Brick> brick(new Brick(k*32,j*32,1000/_FPS,CResourceManager::BRICK,_rm));
						tree->add(brick);
						break;
					}
				case CResourceManager::TYPE_MUSHROOM:
					{
						shared_ptr<MObject> gomba(new Gomba(k*32,j*32,0.05f,0,1000/_FPS,CResourceManager::GOMBAMOVE,_rm));
						tree->add(gomba);
						break;
					}
				case CResourceManager::TYPE_TURTLE:
					{
						shared_ptr<MObject> turtle( new Turtle(k*32,j*32,-0.5f,0,1000/_FPS,CResourceManager::TURBLEMOVELEFT,_rm));
						tree->add(turtle);
						break;
					}
				case CResourceManager::TYPE_STONE:
					{
						shared_ptr<MObject> stone(new MObject(k*32,j*32,0,0,1000/_FPS,CResourceManager::STONE,_rm));
						//stone->LoadResource(_rm);
						tree->add(stone);
						break;
					}
				case CResourceManager::TYPE_MIDLAND:
					{
						shared_ptr<MObject> midland(new MObject(k*32,j*32,0,0,1000/_FPS,CResourceManager::MIDLAND,_rm));
						tree->add(midland);
						break;
					}
				case CResourceManager::TYPE_CHIMNEY3:
					{
						shared_ptr<MObject> chimney(new MObject(k*32,j*32,0,0,1000/_FPS,CResourceManager::CHIMNEY,_rm));
						tree->add(chimney);
						break;
					}
				case CResourceManager::TYPE_COIN:
					{
						shared_ptr<MObject> coin(new MObject(k*32,j*32,0,0,1000/_FPS,CResourceManager::COIN,_rm));
						tree->add(coin);
						break;
					}
				case CResourceManager::TYPE_BOXWITHCOIN:
				case CResourceManager::TYPE_BOXWITHMUSHROOM:
					{
						shared_ptr<MObject> foodbox(new FoodBox(k*32,j*32,1000/_FPS,CResourceManager::QUESTIONBOX,_rm));
						foodbox->setObjectType(i);
						if (_hitBox.size() > 0)
						{
							float x,y;
							for (std::list<Vector>::iterator it = _hitBox.begin(); it!= _hitBox.end();it++)
							{
								if ((*it).getX() == k*32 && (*it).getY() == j*32)
								{
									foodbox->setStatus(FoodBox::STATUS_EMPTY);
									foodbox->setAnimating(false);
								}

							}
						}
						tree->add(foodbox);
						break;
					}

					case CResourceManager::TYPE_PIT:
					{
						shared_ptr<MObject> coin(new MObject(k*32,j*32,0,0,1000/_FPS,CResourceManager::PIT,_rm));
						tree->add(coin);
						break;
						break;
					}

				//
				// insert Sight Items
				case CResourceManager::TYPE_BARRIER:
					{
						shared_ptr<Sight> sight (new Sight(k*32,j*32,1000/_FPS,CResourceManager::BARRIER,_rm));
						_sightList.insert(_sightList.begin(),sight);
						break;
					}

				case CResourceManager::TYPE_CLOUD:
					{
						shared_ptr<Sight> sight (new Sight(k*32,j*32,1000/_FPS,CResourceManager::CLOUD,_rm));
						_sightList.insert(_sightList.begin(),sight);
						break;
					}

				case CResourceManager::TYPE_GRASS:
					{
						shared_ptr<Sight> sight ( new Sight(k*32,j*32,1000/_FPS,CResourceManager::GRASS,_rm));
						_sightList.insert(_sightList.begin(),sight);
						break;
					}

				case CResourceManager::TYPE_HIGHTREE:
					{
						shared_ptr<Sight> sight (new Sight(k*32,j*32,1000/_FPS,CResourceManager::HIGHTREE,_rm));
						_sightList.insert(_sightList.begin(),sight);
						break;
					}

				case CResourceManager::TYPE_SHORTTREE:
					{
						shared_ptr<Sight> sight (new Sight(k*32,j*32,1000/_FPS,CResourceManager::SHORTTREE,_rm));
						_sightList.insert(_sightList.begin(),sight);
						break;
					}
				case CResourceManager::TYPE_COLUMN1:
					{
						shared_ptr<Sight> sight (new Sight(k*32,j*32,1000/_FPS,CResourceManager::COLUMN1,_rm));
						_sightList.insert(_sightList.begin(),sight);
						_finishRect = sight->getRect();
						mario->setXEndMap(_finishRect.left);
						break;
					}
				case CResourceManager::TYPE_COLUMN2:
					{
						shared_ptr<Sight> sight (new Sight(k*32,j*32,1000/_FPS,CResourceManager::COLUMN2,_rm));
						_sightList.insert(_sightList.begin(),sight);
						_winBarX = k*32 - 45;
						_winBarY = j*32 + 25;
						break;
					}
				case CResourceManager::TYPE_MOUNTAIN:
					{
						shared_ptr<Sight> sight (new Sight(k*32,j*32,1000/_FPS,CResourceManager::MOUNTAIN,_rm));
						_sightList.insert(_sightList.begin(),sight);
						break;
					}

				case CResourceManager::TYPE_HOUSE:
					{
						shared_ptr<Sight> sight (new Sight(k*32,j*32,1000/_FPS,CResourceManager::HOUSE,_rm));
						_sightList.insert(_sightList.begin(),sight);
						break;
					}
				case CResourceManager::TYPE_CHECKPOINT:
					{
						Vector v = Vector(k*32,j*32);
						_checkPointList.insert(_checkPointList.end(),v);
						break;
					}
				}
		}
		int countteleport;
		inp>>countteleport;

		for (int i=0;i<countteleport;i++)
		{
			Teleport t = Teleport();
			inp>>t.sourceX;
			inp>>t.sourceY;
			inp>>t.desX;
			inp>>t.desY;
			inp>>t.newRoom;
			inp>>t.screenX;
			inp>>t.screenY;
			_teleList.insert(_teleList.end(),t);
		}
		inp>>_nextMap;
		//if (strcmp("NONEXTMAP",_nextMap))
		int i = 0;
	}
	inp.close();
	_mapLoaded = true;
}

void CMarioGame::NewMap(char* mapfile, char* infoFile)
{
	_MObjectList.clear();
	_staticObjectList.clear();
	_animateList.clear();
	_sightList.clear();
	_teleList.clear();
	_checkPointList.clear();
	_hitBox.clear();
	_allowShoot = true;
	_tScore = 0;
	_startMap = true;
	_cpX = 0;
	_cpY = 0;
	

	if (strlen(infoFile) > 0)
	{
		int length,x,y;
		ifstream inp(infoFile);
		inp>>length;
		for (int i=0;i<length;i++)
		{
			inp>>x;
			inp>>y;
			Vector v = Vector(x,y);
			_hitBox.insert(_hitBox.end(),v);
		}
		inp.close();
	}

	LoadMap(mapfile);
	setStatus(STATUS_PLAYING);
	mario->setStatus(CMario::STATUS_ALIVE);
	mario->setInNewRoom(false);
}

void CMarioGame::LoadResource()
{
	_rm = new CResourceManager(_directX,L"maps\\config.rc");
	_rm->LoadConfig();
	_rm->LoadResource();

	if (CMarioSound::getInstance()->InitSound(this->_hWnd) == 0)
	{
		MessageBox(NULL,"Sound Init error!","Error",MB_OK);
	}

	_info = CInfo(_rm);

	_background = _directX->LoadSurface(_rm->getLink(CResourceManager::BACKGROUND),D3DCOLOR_XRGB(0,0,0));
	_bar = _rm->getSprite(CResourceManager::BAR);

	mario = shared_ptr<CMario>(new CMario(10,0,0,0,1000/_FPS,CResourceManager::MARIOSTANDLEFT1,_rm));
	mario->setLevel(1,false);
	
	if (strlen(_testMap) > 0)
		NewMap(_testMap,"");
	else
		setStatus(STATUS_MENU);
}

void CMarioGame::OnKeyDown(int KeyCode)
{
	if (_gameStatus == STATUS_MENU)
	{
		if (KeyCode == DIK_ESCAPE)
				setStatus(STATUS_MENU);
		return;
	}
	if (mario->getStatus() == CMario::STATUS_MOVENEXTMAP && mario->getLife()>=1)
		return;
	switch (KeyCode)
	{
	case DIK_LEFT:
		{
			
			mario->MoveLeft();
			break;
		}
	case DIK_RIGHT:
		{
			
			mario->MoveRight();
			break;
		}
	case DIK_SPACE:
		{
			mario->Jump();
			if (mario->getAllowJump())
				mario->setAllowJump(false);
			break;
		}
	case DIK_DOWN:
		{
			if (_teleList.size() > 0)
			{
				int k;
				for (std::list<Teleport>::iterator it = _teleList.begin(); it != _teleList.end(); it++)
				{
					k = mario->getPosition().getX() - (*it).sourceX;
					if (k > 3 && k < 32)
					{
						mario->setStatus(CMario::STATUS_TOPIPE);
						mario->setTeleport((*it).desX + 10,(*it).desY);
						if ((*it).newRoom == 1)
						{
							mario->setInNewRoom(true);
							mario->setNewRoomPos(Vector((*it).screenX,(*it).screenY));
						}
						else mario->setInNewRoom(false);
					}
						
				}
			}

			break;
		}
	
	case DIK_Z:
		{
			if (mario->getStatus() != CMario::STATUS_ALIVE && mario->getStatus() != CMario::STATUS_CHANGINGLEVEL)
				break;
			if (_delayShootTime > 0 || !_allowShoot) break;
			if (mario->getLevel() < 3) break;
			float tv;
			float tx;
			if (mario->getLastDir() == CMario::DIR_LEFT)
			{
				tv = -0.8f;
				tx = -17.f;
			}
			else 
			{
				tv = 0.8f;
				tx = 33.f;
			}
			std::shared_ptr<CBullet> bullet(new CBullet(mario->getPosition().getX() + tx,mario->getPosition().getY() + 15.f,tv,0,1000/_FPS,CResourceManager::BULLET,_rm));
			_MObjectList.insert(_MObjectList.end(),bullet);
			_delayShootTime = 15;
			_allowShoot = false;
			CMarioSound::getInstance()->Play(CMarioSound::SOUND_SHOOT, false);
			break;
		}
	case DIK_ESCAPE:
		{
			if (strlen(_testMap) != 0)
				exit(0);
			else
				setStatus(STATUS_MENU);
			break;
		}
	default:
		{
			
			break;
		}
	}
}

void CMarioGame::OnKeyUp(int KeyCode)
{
	switch (KeyCode)
	{
	case DIK_SPACE:
		{
			if (!(mario->getAllowJump()))
				mario->setAllowJump(true);
			break;
		}

	case DIK_Z:
		{
			_allowShoot = true;
			break;
		}
	}
}

void CMarioGame::SaveGame(char* fileName, char* infoFile)
{
	float minLength = MAXINT;
	float cpX = 0;
	float cpY = 0;
	for (std::list<Vector>::iterator it = _checkPointList.begin(); it != _checkPointList.end(); it++)
	{
		if ((*it).getX() <= mario->getPosition().getX())
		{
			if ((mario->getPosition().getX() - (*it).getX()) < minLength)
			{
				cpX = (*it).getX();
				cpY = (*it).getY();
				minLength = mario->getPosition().getX() - cpX;
			}
		}
	}
	if (cpX >= _cpX && cpY >= _cpY)
	{
		_cpX = cpX;
		_cpY = cpY;
	}

	Vector v = tree->getSize();
	int w = v.getX()/32;
	int h = v.getY()/32;
	ofstream out(fileName);
	out<<w<<" ";
	out<<h<<" ";
	out<<mario->getLevel()<<" ";
	out<<mario->getLife()<< " ";
	out<<_cpX<<" ";
	out<<_cpY<<" ";
	out<<mario->getCoin()<<" ";
	out<<mario->getScore()<<endl;

	int** map;
	
	map = new int*[h];
	for (int i=0;i<h;i++)
		map[i] = new int[w];

	for (int i=0;i<h;i++)
		for (int j=0;j<w;j++)
			map[i][j] = 0;

	int indexW, indexH;

	std::list<shared_ptr<MObject>> allObject = tree->getRoot()->getAllObjectList();
	allObject.insert(allObject.end(),_MObjectList.begin(),_MObjectList.end());

	for (std::list<shared_ptr<MObject>>::iterator it = allObject.begin(); it!= allObject.end(); it++)
	{
		indexW = (*it)->getPosition().getX()/32;
		indexH = (*it)->getPosition().getY()/32;
		map[indexH][indexW] = (*it)->getObjectType();
	}

	for (std::list<shared_ptr<Sight>>::iterator it = _sightList.begin(); it!= _sightList.end(); it++)
	{
		indexW = (*it)->getRect().left/32;
		indexH = (*it)->getRect().top/32;
		map[indexH][indexW] = (*it)->getSightType();
	}

	for (std::list<Vector>::iterator it = _checkPointList.begin(); it!= _checkPointList.end(); it++)
	{
		indexW = (*it).getX()/32;
		indexH = (*it).getY()/32;
		map[indexH][indexW] = CResourceManager::TYPE_CHECKPOINT;
	}

	for(int i=0;i<h;i++)
	{
		for (int j=0;j<w-1;j++)
			out<<map[i][j]<<" ";
		out<<map[i][w-1]<<endl;
	}

	out<<_teleList.size()<<endl;
	for(std::list<Teleport>::iterator it = _teleList.begin(); it!= _teleList.end(); it++)
	{
		out<<(*it).sourceX<<" ";
		out<<(*it).sourceY<<" ";
		out<<(*it).desX<<" ";
		out<<(*it).desY<<" ";
		out<<(*it).newRoom<<" ";
		out<<(*it).screenX<<" ";
		out<<(*it).screenY<<endl;
	}
	out<<_nextMap;

	out.close();

	for (int i=0;i<h;i++)
			delete []map[i];
	delete []map;

	ofstream out2(infoFile);
	out2<<_hitBox.size()<<endl;
	for (std::list<Vector>::iterator it = _hitBox.begin(); it!= _hitBox.end(); it++)
		out2<<(*it).getX()<<" "<<(*it).getY()<<endl;
	out2.close();
}

void CMarioGame::setStatus(int Status)
{
	_gameStatus = Status;
	switch (Status)
	{
	case STATUS_PLAYING:
		{
				
				_background = _directX->LoadSurface(_rm->getLink(CResourceManager::BACKGROUND),D3DCOLOR_XRGB(0,0,0));
				CMarioSound::getInstance()->Stop(CMarioSound::SOUND_MENU);
				CMarioSound::getInstance()->Play(CMarioSound::SOUND_BACKGROUND,true);
				break;
		}
	case STATUS_MENU:
		{
				_info.setViewHelp(false);
				CMarioSound::getInstance()->Stop(CMarioSound::SOUND_BACKGROUND);
				CMarioSound::getInstance()->Play(CMarioSound::SOUND_MENU,true);
				_background = _directX->LoadSurface(_rm->getLink(CResourceManager::MAINMENU),D3DCOLOR_XRGB(0,0,0));
				break;
		}
	}
}